<!--
 * @Author: pmy
 * @Date: 2021-09-02 14:39:12
 * @LastEditTime: 2022-11-25 09:57:21
 * @LastEditors: pmy
 * @Description: 通用-table
 * @FilePath: \bdcar-net\src\components\table\baseTable.vue
-->
<template>
    <div class="tablePage" v-loading="loading">
        <div class="search">
            <!-- 查询条件 -->
            <div class="header-query" v-for="(v,k) in query" :key="k" v-show="v.showBy && v.showValue ? query[v.showBy].value == v.showValue : true">
                <span class="search-text">{{v.name}}</span>
                <el-select v-if="v.type=='select'" v-model="v.value" :placeholder="v.placeholder" filterable class="search-input"
                    @change="pagination.currentPage = 1;">
                    <el-option v-for="vv in optionList[k]" :key="vv.value" :label="vv.label" :value="vv.value">
                    </el-option>
                </el-select>
                <el-input v-else-if="v.type=='input'" clearable v-model="v.value" :placeholder="v.placeholder" class="search-input"
                    @change="pagination.currentPage = 1;" @keyup.native.enter="pagination.currentPage = 1;"></el-input>
                <el-cascader v-else-if="v.type == 'cascader'" v-model="v.value" class="search-input" :placeholder="v.placeholder"
                    :options="optionList[v.prop]" :props="cascaderSet" :clearable="false"></el-cascader>
                <el-date-picker v-else-if="v.type=='time'" v-model="v.value" :type="v.timeType ? v.timeType : 'daterange'" range-separator="至"
                    :start-placeholder="v.placeholder[0]" :clearable="false" :end-placeholder="v.placeholder[1]"
                    :picker-options="pickerOptions" class="search-input time-picker" :format="v.format ? v.format :'yyyy-MM-dd'"
                    :value-format="v.valueFormat ? v.valueFormat : 'yyyy-MM-dd'">
                </el-date-picker>
            </div>


            <!-- 按钮 -->
            <div class="search-btn" @click="getTableData()" v-if="Btn.search">
                <div class="btn-img"></div>生成预测
            </div>
            <div class="add-btn" @click="handleClick(null, 'add')" v-if="Btn.add"
                v-show="btnPermissionSearch('basicData', 'fileManage', 'add')">
                <div class="btn-img"></div>新增
            </div>
            <div :class="{ 'export-btn': true, 'disabled': noFileCanDownload }" @click="handleClick(null, 'export')"
                v-if="Btn.export" v-loading="exportLoading">
                <div class="btn-img"></div>
                {{ !exportLoading ? "下载预测" : "下载预测中" }}
            </div>
            <div class="deletes-btn" @click="handleClick(null, 'deletes')" v-if="Btn.deletes"
                v-show="btnPermissionSearch('basicData', 'fileManage', 'deletes')">
                批量删除
            </div>
        </div>
        <div class="base-table" v-if="tableItems != null">
            <el-table highlight-current-row ref="myTable" :data="tableData" @selection-change="handleSelectionChange"
                height="100%">
                <el-table-column :prop="v.prop" :label="v.name" v-for="v in tableItems" :key="v.prop" show-overflow-tooltip
                    :sortable="v.sortable" :header-align="v.align ?? 'right'" :align="v.align ?? 'right'">
                    <template slot-scope="scope">
                        <el-image v-if="v.type == 'img'" :src="imgUrlPrefix + scope.row[v.prop]"
                            style="width:3rem;height:3rem" :preview-src-list="[imgUrlPrefix + scope.row[v.prop]]" />
                        <span v-else-if="scope.row[v.prop] !== ''">{{ scope.row[v.prop] }}</span>
                        <span v-else>---</span>
                    </template>
                </el-table-column>
            </el-table>
        </div>
        <div class="pagination">
            <el-pagination :page-size="pagination.pageSize" @size-change="handleSizeChange"
                @current-change="handleCurrentChange" :current-page="pagination.currentPage" :total="pagination.total"
                :page-sizes="[15, 50, 100, 300]" background layout="total,sizes, prev, pager, next, jumper"></el-pagination>
        </div>
        <!-- 增删查改页面 -->
        <el-dialog v-dialogDrag :close-on-click-modal="false" :visible="showDialog" width="56rem"
            :before-close="closeDialog">

            <template #title>
                <div class='dialog-title'>
                    <div class="cicle"></div>
                    {{ dialogTitle[showWhich] }}
                </div>
            </template>
            <div class="body" v-if="!!showDialog" v-loading="uploading">
                <el-form :model="updateInfo" :inline="true" ref="addformRef" :rules="addformRules">
                    <el-form-item v-for="v in updateItems" :key="v.prop" :label="v.name" :prop="v.prop">
                        <el-input v-model="updateInfo[v.prop]" :disabled="showWhich == 'detail' || v.disabled"
                            v-if="v.type == 'input'"></el-input>
                        <el-input type="textarea" v-else-if="v.type == 'textarea'" :autosize="{ minRows: 2 }"
                            placeholder="请输入内容" :disabled="showWhich == 'detail'" style="width:38rem"
                            v-model="updateInfo[v.prop]"></el-input>
                        <el-date-picker v-model="updateInfo[v.prop]" type="datetime" placeholder="选择时间"
                            value-format="yyyy-MM-dd HH:mm:ss" :disabled="showWhich == 'detail'"
                            v-else-if="v.type == 'time'">
                        </el-date-picker>
                        <el-select v-model="updateInfo[v.prop]" filterable clearable :disabled="showWhich == 'detail'"
                            v-else-if="v.type == 'select'">
                            <el-option v-for="item in optionList[v.prop]" :key="item.id" :label="item.value"
                                :value="item.id">
                            </el-option>
                        </el-select>
                        <treeSelect v-model="updateInfo[v.prop]" :data="optionList[v.prop]" v-else-if="v.type == 'cascader'"
                            :disabled="showWhich == 'detail'" class="search-input">
                        </treeSelect>
                        <file-control ref="myFileControl" :fileHttp="ImportAPI" :getFileName="getFileName"
                            :readOnly="showWhich == 'detail'" :downloadMethod="method.downloadMethod"
                            :pFileList="updateInfo[v.prop] || []" :uploadMethod="method.uploadData"
                            v-else-if="v.type == 'upload'"></file-control>
                    </el-form-item>
                </el-form>
            </div>
            <div class="tool-bar">
                <div class="cancel-btn" @click="closeDialog">关闭</div>
                <div class="submit-btn" @click="handleSubmitFile" v-show="showWhich !== 'detail'">确定</div>
            </div>
        </el-dialog>
    </div>
</template>

<script>
import treeSelect from "@/components/common/treeSelect"
import { service } from "../../services/backServices"
import FileControl from '@/components/common/FileControl.vue';
import { saveAs } from "file-saver";
import { export_json_to_excel } from "@/assets/js/FilExport";
import dayjs from "dayjs";
export default {
    props: [
        "query",//查询参数
        "tableItems",//表格表头
        "updateItems",//增删查改的对象属性
        "optionList",//增删查改的对象属性的下拉select或者级联casual
        "Btn",//自定义btn功能
        "menuName",//权限-菜单名称
        "pageName",//权限-页面名称
    ],
    components: { treeSelect, FileControl },
    data() {
        return {
            imgUrlPrefix: GlobalSetting.imgUrlPrefix,
            uploading: false,
            exportLoading: false,
            loading: false,
            methodParam: "getPopPredict",
            method: {},
            //表格参数
            pagination: {
                total: 0,
                currentPage: 1,
                pageSize: 50,
            },
            multipleSelection: [],
            tableData: [],
            showWhich: "",
            updateInfo: {
                fileName: ''
            },
            params: {},
            cascaderSet: {
                value: 'value',
                emitPath: false,
                checkStrictly: false,
                expandTrigger: 'hover',
                multiple: false
            },
            popFileKey: null,
            prompFileKey: null,
            addformRules: {
                fileName: [
                    { required: true, message: '文件名称', trigger: 'blur' },
                ],
                fileAdd: [
                    { required: true, message: '上传文件', trigger: 'blur' },
                ],
                uploadType: [
                    { required: true, message: '上传类型', trigger: 'change' },
                ]
            },
            pickerOptions: {
                shortcuts: [
                    {
                        text: "最近一天",
                        onClick(picker) {
                            const end = new Date();
                            const start = new Date();
                            start.setTime(start.getTime() - 3600 * 1000 * 24 * 1);
                            picker.$emit("pick", [start, end]);
                        },
                    },
                    {
                        text: "最近两天",
                        onClick(picker) {
                            const end = new Date();
                            const start = new Date();
                            start.setTime(start.getTime() - 3600 * 1000 * 24 * 2);
                            picker.$emit("pick", [start, end]);
                        },
                    },
                    {
                        text: "最近三天",
                        onClick(picker) {
                            const end = new Date();
                            const start = new Date();
                            start.setTime(start.getTime() - 3600 * 1000 * 24 * 3);
                            picker.$emit("pick", [start, end]);
                        },
                    }
                ],
                disabledDate: (time) => {
                    return time.getTime() > Date.now() - 8.64e7;
                },
            },
            pickerOptionsMonth: {
                shortcuts: [{
                    text: '本月',
                    onClick(picker) {
                        picker.$emit('pick', [new Date(), new Date()]);
                    }
                }, {
                    text: '今年至今',
                    onClick(picker) {
                        const end = new Date();
                        const start = new Date(new Date().getFullYear(), 0);
                        picker.$emit('pick', [start, end]);
                    }
                }, {
                    text: '最近六个月',
                    onClick(picker) {
                        const end = new Date();
                        const start = new Date();
                        start.setMonth(start.getMonth() - 6);
                        picker.$emit('pick', [start, end]);
                    }
                }]
            },
            dialogTitle: {
                add: "新增",
                edit: "编辑",
                detail: "详情"
            },
            showDialog: false,
            tableAllData: [],
        };
    },
    computed: {
        ImportAPI() {
            return GlobalSetting.IotConfig.ftpAPIService;
        },
        noFileCanDownload() {
            return this.popFileKey == null && this.prompFileKey == null
        }
    },
    created() {
        let _this = this;
        function getParam(query) {
            let myForm = new FormData()
            Object.keys(query).forEach((key) => {
                if (Array.isArray(query[key]) && key.search(/[Tt]ime/) !== -1) {
                    myForm.append('beginDate', query[key].length ? query[key][0] : '')
                    myForm.append('endDate', query[key].length ? query[key][1] : '')
                } else if (query[key] !== "") {
                    myForm.append(key, query[key])
                }
            })

            return myForm
        };
        _this.method.getData = async function (query) {
            let url = _this.methodParam;
            return service({
                url: url,
                method: "post",
                data: getParam(query)
            });
        };
        _this.method.addData = async function (model) {
            return service({
                headers: {
                    'Content-Type': 'application/json'
                },
                method: 'post',
                url: _this.methodParam + "/save",
                data: model,
            });
        };
        _this.method.editData = async function editTrashOverflowData(model) {
            return service({
                headers: {
                    'Content-Type': 'application/json'
                },
                method: 'post',
                url: _this.methodParam + "/update",
                data: model,
            });
        };
        _this.method.deleteData = async function (id) {
            let url = _this.methodParam + "/remove";
            return service({
                method: 'post',
                url: url,
                params: {
                    id: id
                },
            });
        };
        _this.method.deleteDatas = async function (ids) {
            return service({
                method: 'post',
                url: _this.methodParam + "/batchRemove",
                params: {
                    ids: ids
                },
                paramsSerializer: params => {
                    return qs.stringify(params, {
                        indices: false
                    })
                }
            });
        };
        _this.method.uploadData = async function (data) {
            return service({
                headers: {
                    'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryqs8javp5GsOgKvoQ'
                },
                method: 'post',
                url: _this.methodParam + "/upload",
                data: data,
                params: {
                    uploadType: _this.updateInfo.uploadType
                }
            });
        };
        _this.method.downloadMethod = async function (url) {
            return service({
                method: 'post',
                url: _this.methodParam + "/download",
                responseType: 'blob',
                data: {
                    url: url
                },
            });
        };
    },
    mounted() {

    },
    methods: {
        setTableData() {
            this.tableData = this.tableAllData.slice(
                (this.pagination.currentPage - 1) * this.pagination.pageSize,
                this.pagination.currentPage * this.pagination.pageSize
            )
        },
        //表格参数改变触发
        handleSizeChange: function (val) {
            this.pagination.pageSize = val;
            this.setTableData();
        },
        handleCurrentChange: function (currentPage) {
            this.pagination.currentPage = currentPage;
            this.setTableData();
        },
        getTableData() {
            this.popFileKey = null
            this.prompFileKey = null
            this.loading = true
            for(let k in this.query){
                this.params[k] = this.query[k].value
            }
            this.method.getData(this.params).then(response => {
                this.loading = false
                if (response.data.code == 200) {
                    this.popFileKey = response.data.data.popResPath
                    this.prompFileKey = response.data.data.prompResPath
                }
            })
        },
        handleSelectionChange(val) {
            this.multipleSelection = [];
            val.forEach(v => {
                this.multipleSelection.push(v.id);
            })
        },
        getFileName(val) {
            let title = ''
            if (val && val.length > 0) {
                for (let i = 0; i < val.length - 1; i++) {
                    title += val[i]
                }
            } else {
                title = ''
            }
            this.updateInfo.fileName = title
            this.$forceUpdate();
        },
        // 增删改查
        handleClick(row, obj) {
            if (this.uploading) {
                this.$message({
                    message: '存在正在上传的文件，请等待数据上传成功再试',
                    type: 'warning'
                });
                return
            }
            switch (obj) {
                case "add":
                    this.updateInfo = {};
                    this.showWhich = obj;
                    this.showDialog = true
                    this.$nextTick(() => {
                        this.$refs.addformRef.clearValidate();
                    })
                    break;
                case "edit":
                    this.updateInfo = JSON.parse(JSON.stringify(row));
                    this.showWhich = obj;
                    this.showDialog = true
                    this.$nextTick(() => {
                        this.$refs.addformRef.clearValidate();
                    })
                    break;
                case "detail":
                    this.updateInfo = JSON.parse(JSON.stringify(row));
                    this.showWhich = obj;
                    this.showDialog = true
                    break;
                case "delete":
                    this.deleteData(row.id);
                    break;
                case "deleteMany":
                    this.deleteManyData();
                    break;
                case "export":
                    this.exportTable();
                    break;
                default:
                    break;
            }
        },
        handleSubmitFile() {
            if (!this.updateInfo.uploadType && this.updateInfo.uploadType != 0) {
                this.$message({
                    message: '上传类型不能为空',
                    type: 'warning'
                });
                return
            }
            this.handleSubmit();
            // this.$refs.addformRef.validate((valid) => {
            //   if (valid) {
            //     this.handleSubmit();
            //   }
            // })
        },
        //提交事件
        async handleSubmit() {
            let _this = this;
            const fileDom = this.$refs.myFileControl
            if (fileDom && fileDom[0]) {
                this.uploading = true
                let fileList = await fileDom[0].uploadInfo(), propName = 'file'
                this.uploading = false
                if (!!fileList) {
                    _this.updateInfo[propName + 'AddStr'] = JSON.stringify(fileList);   //去掉最后一个逗号避免后端报错，再加上中括号构造json字符串          
                    _this.updateInfo['fileName'] = fileList[0].name;    //从上传的文件中读取文件名
                }
                if (fileDom[0]?.delFileList?.length > 0) {       // 将删除的图片由数组转为字符串拼接
                    _this.updateInfo[propName + 'DelStr'] = JSON.stringify(fileDom[0].delFileList)
                }
            }
            if (!_this.updateInfo.fileName) {
                this.$message({
                    message: '文件不能为空',
                    type: 'warning'
                });
                return
            }
            switch (this.showWhich) {
                case 'add':
                    this.addInfo();
                    break;
                case 'edit':
                    this.editInfo();
                    break;
            }
        },
        addInfo() {
            let _this = this;
            this.method.addData(_this.updateInfo).then(function (response) {
                if (response.data.code == 0) {
                    _this.getTableData();
                    _this.showWhich = "";
                    _this.showDialog = false
                    _this.$notify({
                        message: "信息保存成功！",
                        type: "success",
                        position: "bottom-right",
                        duration: 2000,
                    });
                }
            }).catch(function (error) {
                _this.$notify({
                    message: "信息保存失败！",
                    type: "error",
                    position: "bottom-right",
                    duration: 2000,
                });
                console.log(error)
            });
        },
        editInfo() {
            let _this = this;
            this.method.editData(_this.updateInfo).then(function (response) {
                if (response.data.code == 0) {
                    _this.getTableData();
                    _this.showWhich = "";
                    _this.showDialog = false
                    _this.$notify({
                        message: "信息保存成功！",
                        type: "success",
                        position: "bottom-right",
                        duration: 2000,
                    });
                }
            }).catch(function (error) {
                _this.$notify({
                    message: "信息保存失败！",
                    type: "error",
                    position: "bottom-right",
                    duration: 2000,
                });
                console.log(error)
            });
        },
        deleteData(id) {
            this.$confirm("此操作将删除该项, 是否继续?", "提示", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning",
            }).then(() => {
                let _this = this;
                _this.method.deleteData(id).then(function (response) {
                    if (response.data.code == 0) {
                        _this.getTableData();
                        _this.showWhich = "";
                        _this.showDialog = false
                        _this.$notify({
                            message: "信息删除成功！",
                            type: "success",
                            position: "bottom-right",
                            duration: 2000,
                        });
                    }
                })
            })
        },
        deleteManyData() {
            let _this = this;
            if (_this.multipleSelection.length > 0) {
                _this.$confirm("此操作将删除该项, 是否继续?", "提示", {
                    confirmButtonText: "确定",
                    cancelButtonText: "取消",
                    type: "warning",
                }).then(() => {
                    _this.method.deleteDatas(_this.multipleSelection).then(function (response) {
                        if (response.data.code == 0) {
                            _this.getTableData();
                            _this.showWhich = "";
                            _this.showDialog = false
                            _this.$notify({
                                message: "信息删除成功！",
                                type: "success",
                                position: "bottom-right",
                                duration: 2000,
                            });
                        }
                    })
                })
            } else {
                this.$notify({
                    message: "请至少选择一项",
                    type: "error",
                    position: "bottom-right",
                    duration: 2000,
                });
            }
        },
        closeDialog() {
            this.showDialog = false
        },
        exportTable() {
            this.exportLoading = true;
            let _this = this;
            debugger
            if (this.popFileKey == null && this.prompFileKey == null) {
                _this.$notify({
                    message: "当前无可下载数据",
                    type: "error",
                    position: "bottom-right",
                    duration: 1000,
                });
                this.exportLoading = false;
                return;
            }
            let fileList = []
            if (this.popFileKey == null) {
                _this.$notify({
                    message: "当前无pop预测数据",
                    type: "warning",
                    position: "bottom-right",
                    duration: 1000,
                });
            } else {
                fileList.push(this.popFileKey)
            }
            if (this.prompFileKey == null) {
                _this.$notify({
                    message: "当前无promp预测数据",
                    type: "warning",
                    position: "bottom-right",
                    duration: 1000,
                });
            } else {
                fileList.push(this.prompFileKey)
            }
            for (let index in fileList) {
                let fileKey = fileList[index];
                service({
                    url: 'downloadResultFile/' + fileKey,
                    method: "get",
                    responseType: 'blob'
                }).then()
            }
            Promise.all(fileList.map(x => service({
                url: 'downloadResultFile/' + x,
                method: "get",
                responseType: 'blob'
            }))).then(rList => {
                rList.map(res => {
                    let filename = res.config.url.split('/')[1];
                    saveAs(res.data, filename);
                })
                _this.exportLoading = false;
            }).catch(() => {
                _this.exportLoading = false;
            })
        },
    },
    activated() {
        let _this = this;
        _this.$nextTick(() => {
        })
    }
}
</script>
<style scoped lang="less">
.tablePage .search {
    .search-btn {
        width: 110px;
    }

    .export-btn {
        width: 110px;

        &.disabled {
            background: gray;
            pointer-events: none;
            cursor: not-allowed;

            .btn-img {
                cursor: not-allowed;
            }
        }
    }
}</style>